package com.enqualcomm.kids.config;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.support.v4.util.SimpleArrayMap;

import com.enqualcomm.kids.component.MyApplication;
import com.squareup.okhttp.internal.DiskLruCache;
import com.squareup.okhttp.internal.Util;
import com.squareup.okhttp.internal.io.FileSystem;

import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.nio.charset.Charset;

import okio.BufferedSink;
import okio.BufferedSource;
import okio.Okio;

/**
 * Created by yinzhiqun on 2016/1/6.
 *
 */
public class ACache {
    private static SimpleArrayMap<String,ACache> mInstanceMap = new SimpleArrayMap<>();
    private static final int APP_VERSION = 1;//app版本，升级时将删除所有缓存
    private static final int VALUE_COUNT = 1;//每个文件存几条数据
    private static final long MAX_SIZE = 300*1024;//LruCache大小,存个1000条也够了
    private static final Charset charset = Charset.forName("UTF-8");

    public static ACache get(String uniqueName){
        return get(uniqueName,APP_VERSION, VALUE_COUNT, MAX_SIZE);
    }

    public static ACache get(String uniqueName,int appVersion,int valueCount,long maxSize){
        ACache aCache = mInstanceMap.get(uniqueName);
        if (aCache==null){
            aCache = new ACache(uniqueName,appVersion, valueCount, maxSize);
            mInstanceMap.put(uniqueName,aCache);
        }
        return aCache;
    }

    private static File getDiskCacheDir(Context context, String uniqueName) {
        String cachePath;
//        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
//                || !Environment.isExternalStorageRemovable()) {
//            File externalCacheDir = context.getExternalCacheDir();
//            if (externalCacheDir!=null){
//                cachePath = externalCacheDir.getPath();
//                return new File(cachePath + File.separator + uniqueName);
//            }
//        }
        cachePath = context.getCacheDir().getPath();
        return new File(cachePath + File.separator + uniqueName);
    }


    private final DiskLruCache diskLruCache;

    private ACache(String uniqueName,int appVersion,int valueCount,long maxSize){
        File diskCacheDir = getDiskCacheDir(MyApplication.getInstance(), uniqueName);
        diskLruCache = DiskLruCache.create(FileSystem.SYSTEM, diskCacheDir, appVersion, valueCount, maxSize);
    }

    public void put(String key,String value){
        String fileName = Util.md5Hex(key);
        DiskLruCache.Editor editor;
        try {
            editor = diskLruCache.edit(fileName);
            BufferedSink sink = Okio.buffer(editor.newSink(0));
            sink.writeString(value, charset).close();
            editor.commit();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public String getString(String key){
        String value = null;
        String fileName = Util.md5Hex(key);
        DiskLruCache.Snapshot snapshot;
        try {
            snapshot = diskLruCache.get(fileName);
            if (snapshot!=null){
                BufferedSource source = Okio.buffer(snapshot.getSource(0));
                value = source.readString(charset);
                source.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return value;
    }

    public void put(String key,Bitmap bitmap){
        String fileName = Util.md5Hex(key);
        DiskLruCache.Editor editor;
        try {
            editor = diskLruCache.edit(fileName);
            BufferedSink sink = Okio.buffer(editor.newSink(0));
            bitmap.compress(Bitmap.CompressFormat.PNG, 100,sink.outputStream());
            sink.close();
            editor.commit();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Bitmap getBitmap(String key){
        Bitmap bitmap = null;
        String fileName = Util.md5Hex(key);
        DiskLruCache.Snapshot snapshot;
        try {
            snapshot = diskLruCache.get(fileName);
            if (snapshot!=null){
                BufferedSource source = Okio.buffer(snapshot.getSource(0));
                bitmap = BitmapFactory.decodeStream(source.inputStream());
                source.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;
    }

    public void put(String key,byte[] bytes){
        String fileName = Util.md5Hex(key);
        DiskLruCache.Editor editor;
        try {
            editor = diskLruCache.edit(fileName);
            BufferedSink sink = Okio.buffer(editor.newSink(0));
            sink.write(bytes).close();
            editor.commit();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public byte[] getByteArray(String key){
        byte[] bytes = null;
        String fileName = Util.md5Hex(key);
        DiskLruCache.Snapshot snapshot;
        try {
            snapshot = diskLruCache.get(fileName);
            if (snapshot!=null){
                BufferedSource source = Okio.buffer(snapshot.getSource(0));
                bytes = source.readByteArray();
                source.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bytes;
    }

    public void put(String key,Serializable serializable){
        String fileName = Util.md5Hex(key);
        DiskLruCache.Editor editor;
        try {
            editor = diskLruCache.edit(fileName);
            BufferedSink sink = Okio.buffer(editor.newSink(0));
            new ObjectOutputStream(sink.outputStream()).writeObject(serializable);
            sink.close();
            editor.commit();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Object getSerializable(String key){
        Object object = null;
        String fileName = Util.md5Hex(key);
        DiskLruCache.Snapshot snapshot;
        try {
            snapshot = diskLruCache.get(fileName);
            if (snapshot!=null){
                BufferedSource source = Okio.buffer(snapshot.getSource(0));
                object = new ObjectInputStream(source.inputStream()).readObject();
                source.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return object;
    }

    public void flush() {
        try {
            diskLruCache.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
